/*   **********************************************************************  **
 **   Copyright notice                                                       **
 **                                                                          **
 **   (c) 2009, Around(J2)ME				                                 **
 **   All rights reserved.                                                   **
 **                                                                          **
 **   This program and the accompanying materials are made available under   **
 **   the terms of the New BSD License which accompanies this    			 **
 **   distribution.											                 **
 **   A copy is found in the textfile LICENSE.txt							 **
 **                                                                          **
 **   This copyright notice MUST APPEAR in all copies of the file!           **
 **                                                                          **
 **   Main developers:                                                       **
 **     Juri Strumpflohner		http://blog.js-development.com	             **
 **		Matthias Braunhofer		http://matthias.jimdo.com                    **
 **                                                                          **
 **  **********************************************************************  */

package org.aroundme.model;

import java.util.ArrayList;
import java.util.List;

import org.aroundme.utility.Constants;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

@SuppressWarnings("unchecked")
/**
 * This class is responsible for encoding the responses (which are
 * send back to the client) into XML
 */
public class XMLResponseEncoder {
	private Document doc;
	
	public XMLResponseEncoder(){
	}
	
	/**
	 * Creates a new instance of Document and
	 * adds a root element to it
	 *
	 */
	private void createNewDoc(){
		Element root = new Element("root");
		doc = new Document();
		doc.setRootElement(root);
	}
	
	/**
	 * 
	 * @param type
	 */
	private void setDocType(String type){
		Element typeEl = new Element("type");
		typeEl.setText(type);
		doc.getRootElement().addContent(typeEl);
	}
	
	/**
	 * Creates a new BodyElement, adds it to the root
	 * and returns it for further editing
	 * @return
	 */
	private Element createAndAddBodyElement(){
		Element bodyEl = new Element("responseBody");
		doc.getRootElement().addContent(bodyEl);
		return bodyEl;
	}
	
	/**
	 * Encodes a list of places into XML
	 * @param places Places to be encoded
	 * @return String containing the places encoded in the XML file
	 */
	public String encodePlacesToXML(List<Place> places){
		createNewDoc();
		setDocType(Constants.DATA_PLACE);
		
		Element bodyEl = createAndAddBodyElement();
		
		for (Place place : places) {
			bodyEl.addContent(createPlaceElement(place));
		}
		
		return createXMLString();
	}
	
	private Element createPlaceElement(Place place){
		Element placeEl = new Element("place");
		Element idEl = new Element("id");
		idEl.setText(String.valueOf(place.getId()));
		Element titleEl = new Element("name");
		titleEl.setText(place.getName());
		Element addressEl = new Element("address");
		addressEl.setText(place.getAddress());		
		Element cityEl = new Element("city");
		cityEl.setText(place.getCity());
		Element creationDateEl = new Element("creationDate");
		DateManager dateManager = new DateManager();
		creationDateEl.setText(dateManager.getSimpleDateFormatter().format(place.getCreationDate()));
		
		Element distanceEl = null;
		if (place.getDistance() != null) {
			distanceEl = new Element("distance");
			distanceEl.setText(String.valueOf(place.getDistance()));
			}
		
		Element userEl = new Element("user");
		userEl.setText(place.getUser().getLoginName());
		
		//attach categories
		Element categoriesEl = new Element("categories");
		List categories = new ArrayList<Category>();
		categories.addAll(place.getCategories());
		for (Object object : categories) {
			Category c = (Category)object;
			categoriesEl.addContent(createCategoryElement(c));
		}
		
		//attach comments
		Element commentsEl = new Element("comments");
		List comments = new ArrayList<Comment>();
		comments.addAll(place.getComments());
		for (Object object : comments) {
			Comment c = (Comment)object;
			commentsEl.addContent(createCommentElement(c));
		}
		
		placeEl.addContent(idEl);
		placeEl.addContent(titleEl);
		placeEl.addContent(addressEl);
		placeEl.addContent(cityEl);
		if (place.getDistance() != null) {
			placeEl.addContent(distanceEl);
		}
		placeEl.addContent(creationDateEl);
		placeEl.addContent(userEl);
		placeEl.addContent(categoriesEl);
		placeEl.addContent(commentsEl);
		
		return placeEl;
	}
	
	private Element createCommentElement(Comment c) {
		Element commentEl = new Element("comment");
		Element idEl = new Element("id");
		idEl.setText("" +c.getId());
		Element contentEl = new Element("content");
		contentEl.setText(c.getComment());
		Element dateEl = new Element("creationDate");
		//TODO NOTE The != null check is only for the unit tests since all comments have a creation date
		if(c.getCreationDate()!=null)
			dateEl.setText(new DateManager().getSimpleDateFormatter().format(c.getCreationDate()));
		Element userEl = new Element("user");
		userEl.setText(c.getUser().getLoginName());
		
		commentEl.addContent(idEl);
		commentEl.addContent(contentEl);
		commentEl.addContent(dateEl);
		commentEl.addContent(userEl);
		
		return commentEl;
	}
	
	private Element createCategoryElement(Category c) {
		Element categoryEl = new Element("category");
		Element idEl = new Element("id");
		idEl.setText("" +c.getId());
		Element nameEl = new Element("name");
		nameEl.setText(c.getName());
		
		categoryEl.addContent(idEl);
		categoryEl.addContent(nameEl);
		
		return categoryEl;
	}

	/**
	 * Encodes an alert into XML
	 * @param alertType Type of the Alert (info, error)
	 * @param message Message of the Alert
	 * @return String containing the Alert encoded in XML
	 */
	public String encodeAlert(String alertType, String message){
		createNewDoc();
		setDocType(Constants.ALERT);
		
		Element bodyEl = createAndAddBodyElement();
		Element alertLevelEl = new Element("level");
		alertLevelEl.setText(alertType);
		Element messageEl = new Element("message");
		messageEl.setText(message);
		
		bodyEl.addContent(alertLevelEl);
		bodyEl.addContent(messageEl);
		
		return createXMLString();
	}
	
	/**
	 * Creates a string out of the JDom document model
	 * @return String containing the whole XML in the Document object
	 */
	private String createXMLString(){
//		doc.setDocType(new DocType("html", "-//W3C//DTD HTML 4.01//EN", "http://www.w3.org/TR/html4/strict.dtd"));
		Format f = Format.getCompactFormat();
		f.setEncoding("ISO-8859-1");
		XMLOutputter outputter = new XMLOutputter(f);
		return outputter.outputString(doc);
	}
}
